package org.albino.evinreisi.facebook;

import java.io.Serializable;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.inject.Named;

import org.apache.commons.lang.StringUtils;
import org.springframework.context.annotation.Scope;

@Named("facebookSession")
@Scope("session")
public class FacebookSession implements Serializable {
	private static final long serialVersionUID = 1922105155154467981L;
	private static final Logger log = Logger.getLogger(FacebookSession.class.getName());

	public enum State {
		DISCONNECTED, CONNECTING, CONNECTED
	}

	private FacebookUser user;
	private String token;
	private State state = State.DISCONNECTED;
	private Long expires;
	
	public boolean isConnected(){
		return getState().equals(FacebookSession.State.CONNECTED);
	}
	
	public boolean isConnecting(){
		return getState().equals(FacebookSession.State.CONNECTING);
	}
	
	public boolean isDisconnected(){
		return getState().equals(FacebookSession.State.DISCONNECTED);
	}
	
	public void revalidateSession() {
		log.finest("revalidateSession is called.");
		if(!needsFacebookCheck()){
			log.finest("revalidateSession is not necessary.");
			return;
		}
		
		log.finest("revalidateSession is necessary.");
		
		FacebookService facebookService = new FacebookServiceImpl(token);
		try {
			FacebookUser facebookUser = facebookService.getSelf();
			log.finest("token is valid. Got facebookUser = " + facebookUser);
			
			if (facebookUser.getId().equals(user.getId())) {
				log.finest("user ids matched, session is valid.");
				return;
			}
			
			log.finest("user ids didnt match, devalidating session!");
		} catch (Exception e) {
			log.log(Level.SEVERE, "token is invalid!", e);
		}
		
		setState(State.DISCONNECTED);
	}
	
	public static FacebookSession buildFacebookSession(String token) {
		log.finest("buildFacebookSession is called.");
		log.finest("token = " + token);
		
		FacebookSession facebookSession = buildFacebookSession();

		if(StringUtils.isEmpty(token))
			return facebookSession;
		
		FacebookService facebookService = new FacebookServiceImpl(token);

		try {
			FacebookUser facebookUser = facebookService.getSelf();
			log.finest("token is valid. Got facebookUser = " + facebookUser);
			facebookSession.setUser(facebookUser);
			facebookSession.setToken(token);
			facebookSession.setState(State.CONNECTED);
		} catch (Exception e) {
			log.log(Level.SEVERE, "token is invalid!", e);
			facebookSession.setState(State.DISCONNECTED);
		}
		
		log.finest("facebookSession = " + facebookSession);
		return facebookSession;
	}
	
	public static FacebookSession buildFacebookSession() {
		log.finest("buildFacebookSession is called.");
		FacebookSession facebookSession = new FacebookSession();
		facebookSession.setState(State.DISCONNECTED);
		log.finest("facebookSession = " + facebookSession);
		return facebookSession;
	}


	public void updateExpireTime() {
		GregorianCalendar calendar = new GregorianCalendar();
		calendar.add(Calendar.SECOND, Integer.parseInt(SystemProperties.get("session.expiration.time.in.seconds")));
		expires = calendar.getTimeInMillis();
	}

	public boolean needsFacebookCheck() {
		if (expires == null)
			return true;
		long now = new GregorianCalendar().getTimeInMillis();

		return now > expires;
	}

	public FacebookUser getUser() {
		return user;
	}

	public void setUser(FacebookUser user) {
		this.user = user;
	}

	public String getToken() {
		return token;
	}

	public void setToken(String token) {
		this.token = token;
	}

	public State getState() {
		return state;
	}

	public void setState(State state) {
		this.state = state;
	}

	public void setExpires(long expires) {
		this.expires = expires;
	}

	public long getExpires() {
		return expires;
	}

	@Override
	public String toString() {
		return "FacebookSession [expires=" + expires + ", state=" + state + ", token=" + token + ", user=" + user + "]";
	}
}
